<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
<meta charset="UTF-8">
<style>
#header {
    background-color:lightgray;
    color:black;
    text-align:left;
    padding:5px;
}
#nav {
    line-height:30px;
    background-color:#eeeeee;
    height:300px;
    width:100px;
    float:left;
    padding:5px;	      
}
#section {
    width:350px;
    float:left;
    padding:10px;	 	 
}
#footer {
    background-color:black;
    color:white;
    clear:both;
    text-align:center;
   padding:5px;	 	 
}
</style>

<title>数字示波器</title>
</head>
<body>
<div id="header">
<h1 style="margin-left: 400px;">数字示波器</h1>
<a href="/index.html" style="margin-right: 50px;">数字示波器</a>
<a href="/generator.html" style="margin-right: 50px;">波形发生器</a>
<a href="/file.html" style="margin-right: 50px;">文件</a>
<a href="/log.html" style="margin-right: 50px;">维测</a>
<label id="Version">版本:</label>
</div>
<p/>
<div style="display:inline-block;">
	<canvas id="canvasWave" style="border:1px solid;" width="1024" height="680"></canvas>
</div>
<div style="display:inline-block; position:absolute;">
	<fieldset>
		<legend>CH0</legend>
		<input type="checkbox" id="Ch0Enable" name="Ch0Enable" value="0" checked onclick="Ch0EnableChange(this)" />
		<label for="Ch0Enable">启用</label>
		<fieldset id = "Ch0Range">
			<legend>电压分度</legend>
			<input type="input" id="Ch0Div" name="Ch0Div" size="6" value="1V" readonly/>
			<input type="button" id="Ch0DivAdd" value="加" onclick="Ch0DivAdd()"/>
			<input type="button" id="Ch0DivDec" value="减" onclick="Ch0DivDec()"/>
		</fieldset>
		<fieldset id = "Ch0Coupling">
			<legend>耦合方式</legend>
			<input type="radio" id="Ch0CouplingDc" name="Ch0Coupling" value="DC" checked onclick="Ch0CouplingChange(this)" />
			<label for="Ch0CouplingDc">直流</label>
			<input type="radio" id="Ch0CouplingAc" name="Ch0Coupling" value="AC" onclick="Ch0CouplingChange(this)" />
			<label for="Ch0CouplingAc">交流</label>
		</fieldset>
	</fieldset>

	<fieldset>
		<legend>CH1</legend>
		<input type="checkbox" id="Ch1Enable" name="Ch1Enable" value="0" checked onclick="Ch1EnableChange(this)" />
		<label for="Ch1Enable">启用</label>
		<fieldset id = "Ch1Range">
			<legend>电压分度</legend>
			<input type="input" id="Ch1Div" name="Ch1Div" size="6" value="1V" readonly/>
			<input type="button" id="Ch1DivAdd" value="加" onclick="Ch1DivAdd()"/>
			<input type="button" id="Ch1DivDec" value="减" onclick="Ch1DivDec()"/>
		</fieldset>
		<fieldset id = "Ch1Coupling">
			<legend>耦合方式</legend>
			<input type="radio" id="Ch1CouplingDc" name="Ch1Coupling" value="DC" checked onclick="Ch1CouplingChange(this)" />
			<label for="Ch1CouplingDc">直流</label>
			<input type="radio" id="Ch1CouplingAc" name="Ch1Coupling" value="AC" onclick="Ch1CouplingChange(this)" />
			<label for="Ch1CouplingAc">交流</label>
		</fieldset>
	</fieldset>
	<fieldset>
		<legend>触发</legend>
		<fieldset>
			<legend>通道</legend>
				<input type="radio" id="TriggerCh0" name="TriggerCh" value="0" checked onclick="TriggerChnlChange(this)"/>
				<label for="TriggerCh0">CH0</label>
				<input type="radio" id="TriggerCh1" name="TriggerCh" value="1" onclick="TriggerChnlChange(this)"/>
				<label for="TriggerCh0">CH1</label>
		</fieldset>
		<fieldset>
			<legend>触发沿</legend>
				<input type="radio" id="TriggerEdgeRising" name="TriggerEdge" value="Rising" checked onclick="TriggerEdgeChange(this)"/>
				<label for="Ch1CouplingDc">上升沿</label>
				<input type="radio" id="TriggerEdgeFalling" name="TriggerEdge" value="Falling" onclick="TriggerEdgeChange(this)"/>
				<label for="Ch1CouplingDc">下降沿</label>
				<input type="radio" id="TriggerEdgeBoth" name="TriggerEdge" value="Both" onclick="TriggerEdgeChange(this)"/>
				<label for="Ch1CouplingDc">双沿</label>
		</fieldset>
		<fieldset>
			<legend>触发模式</legend>
				<input type="radio" id="TriggerModeNormal" name="TriggerMode" value="Normal" checked onclick="TriggerModeChange(this)"/>
				<label for="Ch1CouplingDc">正常</label>
				<input type="radio" id="TriggerModeSingle" name="TriggerMode" value="Single" onclick="TriggerModeChange(this)"/>
				<label for="Ch1CouplingDc">单次</label>
		</fieldset>
	</fieldset>
	<p/>
	<label for="SampleRate">采样率：</label>
	<input type="input" id="SampleRate" name="SampleRate" size="6" value="10000000" disabled/>
	<input type="button" id="Run" value="运行中" onclick="SendWriteRunSetting()"/>
</div>
<div>
<label for="Ch0AvgValue">CH0：</label>
<input type="checkbox" id="Ch0AvgValue" name="Ch0AvgValue" value="0" onclick="MeasueFlagChange(this, 0, 0)"/>
<label for="Ch0AvgValue">平均值</label>
<input type="checkbox" id="Ch0MaxValue" name="Ch0MaxValue" value="0" onclick="MeasueFlagChange(this, 0, 1)"/>
<label for="Ch0MaxValue">最大值</label>
<input type="checkbox" id="Ch0MinValue" name="Ch0MinValue" value="0" onclick="MeasueFlagChange(this, 0, 2)"/>
<label for="Ch0MinValue">最小值</label>
<input type="checkbox" id="Ch0Vpp" name="Ch0Vpp" value="0" onclick="MeasueFlagChange(this, 0, 3)"/>
<label for="Ch0Vpp">摆幅</label>
<input type="checkbox" id="Ch0Freq" name="Ch0Freq" value="0" onclick="MeasueFlagChange(this, 0, 4)"/>
<label for="Ch0Freq">频率</label>
<p/>
<label for="Ch0AvgValue">CH1：</label>
<input type="checkbox" id="Ch1AvgValue" name="Ch1AvgValue" value="0" onclick="MeasueFlagChange(this, 1, 0)"/>
<label for="Ch1AvgValue">平均值</label>
<input type="checkbox" id="Ch1MaxValue" name="Ch1MaxValue" value="0" onclick="MeasueFlagChange(this, 1, 1)"/>
<label for="Ch1MaxValue">最大值</label>
<input type="checkbox" id="Ch1MinValue" name="Ch1MinValue" value="0" onclick="MeasueFlagChange(this, 1, 2)"/>
<label for="Ch1MinValue">最小值</label>
<input type="checkbox" id="Ch1Vpp" name="Ch1Vpp" value="0" onclick="MeasueFlagChange(this, 1, 3)"/>
<label for="Ch1Vpp">摆幅</label>
<input type="checkbox" id="Ch1Freq" name="Ch1Freq" value="0" onclick="MeasueFlagChange(this, 1, 4)"/>
<label for="Ch1Freq">频率</label>
</div>

<script>
	var g_init_done = 0;
	var g_rt_data_json;
	var g_init_cfg_json;

	var g_last_update_time = Date.now();
	var g_frame_cnt = 0;
	var g_frame_fps = 0;

	// FFT实现
	function fft(data) {
		var N = data.length;
		
		// 基本情况
		if (N <= 1) {
			return data;
		}
		
		// 确保N是2的幂
		var power = Math.ceil(Math.log2(N));
		var newSize = Math.pow(2, power);
		
		// 如果需要，用零填充数据
		if (newSize != N) {
			var newData = new Array(newSize);
			for (var i = 0; i < N; i++) {
				newData[i] = data[i];
			}
			for (var i = N; i < newSize; i++) {
				newData[i] = {real: 0, imag: 0};
			}
			data = newData;
			N = newSize;
		}
		
		// 分离偶数和奇数索引
		var even = new Array(N/2);
		var odd = new Array(N/2);
		
		for (var i = 0; i < N/2; i++) {
			even[i] = data[2*i];
			odd[i] = data[2*i + 1];
		}
		
		// 递归计算FFT
		even = fft(even);
		odd = fft(odd);
		
		// 合并结果
		var result = new Array(N);
		for (var k = 0; k < N/2; k++) {
			var theta = -2 * Math.PI * k / N;
			var t = {
				real: Math.cos(theta) * odd[k].real - Math.sin(theta) * odd[k].imag,
				imag: Math.cos(theta) * odd[k].imag + Math.sin(theta) * odd[k].real
			};
			
			result[k] = {
				real: even[k].real + t.real,
				imag: even[k].imag + t.imag
			};
			
			result[k + N/2] = {
				real: even[k].real - t.real,
				imag: even[k].imag - t.imag
			};
		}
		
		return result;
	}


	function FFTGetHz(ch) {
		// 检查是否有数据
		if (!g_rt_data_json || !g_rt_data_json.Points) {
			return 0;
		}
		
		var Points = g_rt_data_json.Points;
		var num = Points.length / 4; // 每个点有4个值
		
		if (num <= 1) {
			return 0;
		}
		
		// 确定通道偏移量
		var offset = ch * 2; // ch0: 0, ch1: 2
		
		// 提取数据并计算平均值
		var data = new Array(num);
		for (var i = 0; i < num; i++) {
			var ch_min = Points[4 * i + offset];
			var ch_max = Points[4 * i + offset + 1];
			data[i] = (ch_min + ch_max) / 2;
		}
		
		// 创建复数数组用于FFT (虚部为0)
		var fftData = new Array(num);
		for (var i = 0; i < num; i++) {
			fftData[i] = {real: data[i], imag: 0};
		}
		
		// 执行FFT
		var fftResult = fft(fftData);
		
		// 寻找最大幅度的频率分量
		var maxMagnitude = 0;
		var maxIndex = 0;
		
		// 只检查前半部分的频率 (奈奎斯特定律)
		for (var i = 1; i < Math.floor(num / 2); i++) {
			var magnitude = Math.sqrt(
				fftResult[i].real * fftResult[i].real + 
				fftResult[i].imag * fftResult[i].imag
			);
			
			if (magnitude > maxMagnitude) {
				maxMagnitude = magnitude;
				maxIndex = i;
			}
		}
		
		// 计算频率
		// 采样率: 1000000.0 / g_init_cfg_json.TimeDivUs (每微秒采样数)
		// 频率 = index * 采样率 / N
		var sampleRate = 1000000.0 / g_init_cfg_json.TimeDivUs * g_init_cfg_json.MaxLength / g_init_cfg_json.TimeDivNum;
		var frequency = maxIndex * sampleRate / num;
		
		return frequency;
	}

		// 格式化频率显示，保留3位有效数字并添加适当单位
	function formatFrequency(ch) {
		var freq = FFTGetHz(ch);
		if (freq <= 0 || isNaN(freq) || !isFinite(freq)) {
			return "Unknown";
		}
		
		var unit = "Hz";
		var value = freq;
		
		if (freq >= 1000000) {
			unit = "MHz";
			value = freq / 1000000;
		} else if (freq >= 1000) {
			unit = "KHz";
			value = freq / 1000;
		}
		
		// 保留3位有效数字
		if (value >= 100) {
			// 3位整数，直接取整
			value = Math.round(value);
		} else if (value >= 10) {
			// 2位整数，保留1位小数
			value = Math.round(value * 10) / 10;
		} else {
			// 1位整数，保留2位小数
			value = Math.round(value * 100) / 100;
		}
		
		return value + unit;
	}


	function UpdateSettingUiFlag() {
		document.getElementById("Ch0AvgValue").checked = g_init_cfg_json.MeasureFlag & (1 << 0);
		document.getElementById("Ch0MaxValue").checked = g_init_cfg_json.MeasureFlag & (1 << 1);
		document.getElementById("Ch0MinValue").checked = g_init_cfg_json.MeasureFlag & (1 << 2);
		document.getElementById("Ch0Vpp").checked = g_init_cfg_json.MeasureFlag & (1 << 3);
		document.getElementById("Ch0Freq").checked = g_init_cfg_json.MeasureFlag & (1 << 4);

		document.getElementById("Ch1AvgValue").checked = g_init_cfg_json.MeasureFlag & (1 << 16);
		document.getElementById("Ch1MaxValue").checked = g_init_cfg_json.MeasureFlag & (1 << 17);
		document.getElementById("Ch1MinValue").checked = g_init_cfg_json.MeasureFlag & (1 << 18);
		document.getElementById("Ch1Vpp").checked = g_init_cfg_json.MeasureFlag & (1 << 19);
		document.getElementById("Ch1Freq").checked = g_init_cfg_json.MeasureFlag & (1 << 20);
	}

	function UpdateSettingUi(responseText) {
		console.log("initSetting:" + responseText);
		g_init_cfg_json = JSON.parse(responseText);
		if (g_init_cfg_json.Runing == 1) {
			document.getElementById("Run").value = "运行中";
		} else {
			document.getElementById("Run").value = "已停止";
		}
		document.getElementById("SampleRate").value = parseInt(g_init_cfg_json.SampleRate);
		document.getElementById("TriggerCh" + g_init_cfg_json.TriggerCh).checked = true;
		document.getElementById("TriggerEdge" + g_init_cfg_json.TriggerEdge).checked = true;
		document.getElementById("Ch0Enable").checked = g_init_cfg_json.Ch0Enable;
		document.getElementById("Ch1Enable").checked = g_init_cfg_json.Ch1Enable;
		document.getElementById("TriggerMode" + g_init_cfg_json.TriggerMode).checked = true;
		g_max_length = g_init_cfg_json.MaxLength;
		document.getElementById("Ch0Div").value = g_init_cfg_json.Ch0Div + "mV";
		document.getElementById("Ch1Div").value = g_init_cfg_json.Ch1Div + "mV";
		UpdateSettingUiFlag();
	}

	function SendReadSettingRequesetCb(responseText) {
		UpdateSettingUi(responseText);
		if (g_init_done == 0) {
			g_init_done = 1;
			SendReadWaveRequeset();
		}
	}

	function SendReadSettingRequeset(responseText) {
		SendHttpRequest("/setting.json", SendReadSettingRequesetCb);
	}

	function SendWriteSettingRequeset(setting) {
		SendHttpRequest("/setting.cgi" + "?" + setting, SendReadSettingRequeset);
	}

	function SendReadWaveRequesetCb(responseText) {
		UpdateWaveUi(responseText);
		SendReadWaveRequeset();
	}

	function SendReadWaveRequeset() {
		SendHttpRequest("/snap.json", SendReadWaveRequesetCb);
	}

	function SendHttpRequest(url, callback) {
		var xhttp = new XMLHttpRequest();
		xhttp.onreadystatechange = function() {
			if (this.readyState == 4 && this.status == 200) {
				if (callback) {
					callback(this.responseText);
				}
				xhttp.abort();
			}
		};
		xhttp.open("GET", url, true);
		xhttp.send();
	}

	function UpdateWaveUiBackGrid() {
		var canvas = document.getElementById("canvasWave");
		var ctx = canvas.getContext("2d");

		if (g_init_cfg_json == null) {
			return;
		}
		ctx.fillStyle = "black";
		ctx.strokeStyle  = "black";
		ctx.beginPath();
		ctx.setLineDash([2, 6]);
		for (i = 0; i < g_init_cfg_json.TimeDivNum - 1; i++) {
			ctx.moveTo(0, parseInt(canvas.height / g_init_cfg_json.TimeDivNum * (i + 1)));
			ctx.lineTo(parseInt(canvas.width), parseInt(canvas.height / g_init_cfg_json.TimeDivNum * (i + 1)));

			ctx.moveTo(parseInt(canvas.width / g_init_cfg_json.TimeDivNum * (i + 1)), 0);
			ctx.lineTo(parseInt(canvas.width / g_init_cfg_json.TimeDivNum * (i + 1)), parseInt(canvas.height));
		}
		ctx.stroke();
	}

	function UpdateWaveStatus() {
		var btn_status = document.getElementById("Run");

		if (g_rt_data_json.Status == "Running") {
			btn_status.value = "运行中";
		}
		if (g_rt_data_json.Status == "Stopped") {
			btn_status.value = "已停止";
		}
	}

	function UpdateWaveDataCh(ch) {
		var canvas = document.getElementById("canvasWave");
		var ctx = canvas.getContext('2d');
		var gridW = 0, gridCh, offset = 0;
		var Points = g_rt_data_json.Points;
		var num = Points.length / 4;
		var gnd;
		var hoffset = g_rt_data_json.Offset;

		gridW = canvas.width * 1.0 / g_max_length;
		if (ch == 0) {
			offset = 0;
			gnd = g_init_cfg_json.Ch0Gnd;
			gridCh = canvas.height * 1.0 / g_init_cfg_json.Ch0Div / g_init_cfg_json.TimeDivNum;
			ctx.fillStyle = "red";
			ctx.strokeStyle  = "red";
		} else {
			offset = 2;
			gnd = g_init_cfg_json.Ch1Gnd;
			gridCh = canvas.height * 1.0 / g_init_cfg_json.Ch1Div / g_init_cfg_json.TimeDivNum;
			ctx.fillStyle = "green";
			ctx.strokeStyle  = "green";
		}

		ctx.beginPath();
		ctx.setLineDash([4, 0]);
		ctx.moveTo(hoffset * gridW, canvas.height / 2 - (Points[offset] + gnd) * gridCh);
		for (i = 0; i < num; i++) {
			var ch_min = parseInt(Points[4 * i + offset + 0]);
			var ch_max = parseInt(Points[4 * i + offset + 1]);

			//console.log("ch_min:" + ch_min + " ch_max:" + ch_max);
			ctx.lineTo(parseInt((i + hoffset) * gridW), parseInt(canvas.height / 2 - (ch_min + gnd) * gridCh));
			ctx.lineTo(parseInt((i + hoffset) * gridW), parseInt(canvas.height / 2 - (ch_max + gnd) * gridCh));
		}
		ctx.stroke();
	}

	function CheckFlag(ch, index) {
		if (g_init_cfg_json == null) {
			return 0;
		}
		if (g_init_cfg_json.MeasureFlag & (1 << (index + ch * 16))) {
			return 1;
		}
		return 0;
	}

	function UpdateWaveMeasueCh(ch) {
		var canvas = document.getElementById("canvasWave");
		var ctx = canvas.getContext('2d');
		var gridCh, offset = 0;
		var Points = g_rt_data_json.Points;
		var num = Points.length / 4;
		var gnd;

		if (ch == 0) {
			offset = 0;
			gnd = g_init_cfg_json.Ch0Gnd;
			gridCh = canvas.height * 1.0 / g_init_cfg_json.Ch0Div / g_init_cfg_json.TimeDivNum;
			ctx.fillStyle = "red";
			ctx.strokeStyle  = "red";
		} else {
			offset = 2;
			gnd = g_init_cfg_json.Ch1Gnd;
			gridCh = canvas.height * 1.0 / g_init_cfg_json.Ch1Div / g_init_cfg_json.TimeDivNum;
			ctx.fillStyle = "green";
			ctx.strokeStyle  = "green";
		}

		ctx.beginPath();
		var sum = 0;
		var iMin = parseInt(Points[offset + 0]);
		var iMax = parseInt(Points[offset + 1]);
		for (i = 0; i < num; i++) {
			var ch_min = parseInt(Points[4 * i + offset + 0]);
			var ch_max = parseInt(Points[4 * i + offset + 1]);

			sum += (ch_min + ch_max) / 2;
			if (ch_min > iMax) {
				iMax = ch_min;
			}
			if (ch_min < iMin) {
				iMin = ch_min;
			}
			if (ch_max > iMax) {
				iMax = ch_max;
			}
			if (ch_max < iMin) {
				iMin = ch_max;
			}
		}
		sum = parseInt(sum / num * 10) / 10;

		var pos = 0;
		ctx.font="15px Arial";
		if (CheckFlag(ch, 0)) {
			ctx.fillText("CH" + ch + " Vavg:" + sum + "mV", pos, canvas.height * (38 + ch) / 40);
			pos += canvas.width / 5;
		}
		if (CheckFlag(ch, 1)) {
			ctx.fillText("CH" + ch + " Vmax:" + iMax + "mV", pos, canvas.height * (38 + ch) / 40);
			pos += canvas.width / 5;
		}
		if (CheckFlag(ch, 2)) {
			ctx.fillText("CH" + ch + " Vmin:" + iMin + "mV", pos, canvas.height * (38 + ch) / 40);
			pos += canvas.width / 5;
		}
		if (CheckFlag(ch, 3)) {
			ctx.fillText("CH" + ch + " Vpp:" + (iMax - iMin) + "mV", pos, canvas.height * (38 + ch) / 40);
			pos += canvas.width / 5;
		}
		if (CheckFlag(ch, 4)) {
			ctx.fillText("CH" + ch + " Freq:" + formatFrequency(ch), pos, canvas.height * (38 + ch) / 40);
			pos += canvas.width / 5;
		}
		ctx.stroke();
	}

	function UpdateWaveGnd() {
		var canvas = document.getElementById("canvasWave");
		var ctx = canvas.getContext('2d');
		var y_pos = 0;

		ctx.beginPath();
		ctx.setLineDash([4, 4]);
		ctx.fillStyle = "blue";
		ctx.strokeStyle  = "blue";
		ctx.font = "15px Arial";			
		if (g_init_cfg_json.TriggerCh == 0) {
			y_pos = canvas.height / 2 - canvas.height * (g_init_cfg_json.Ch0Gnd + g_init_cfg_json.TriggerLevel) / g_init_cfg_json.Ch0Div / g_init_cfg_json.TimeDivNum;
		} else {
			y_pos = canvas.height / 2 - canvas.height * (g_init_cfg_json.Ch1Gnd + g_init_cfg_json.TriggerLevel) / g_init_cfg_json.Ch1Div / g_init_cfg_json.TimeDivNum;
		}
		ctx.moveTo(0, parseInt(y_pos));
		ctx.lineTo(parseInt(canvas.width), parseInt(y_pos));
		ctx.fillText("Trigger", 0, y_pos);
		ctx.stroke();

		if (g_init_cfg_json.Ch0Enable) {
			ctx.beginPath();
			ctx.setLineDash([4, 4]);
			ctx.fillStyle = "red";
			ctx.strokeStyle  = "red";
			ctx.font = "15px Arial";
			y_pos = canvas.height / 2 - canvas.height * g_init_cfg_json.Ch0Gnd  / g_init_cfg_json.Ch0Div / g_init_cfg_json.TimeDivNum;
			ctx.moveTo(0, parseInt(y_pos));
			ctx.lineTo(parseInt(canvas.width), parseInt(y_pos));
			ctx.fillText("Ch0Gnd", 0, y_pos);
			ctx.stroke();
		}

		if (g_init_cfg_json.Ch1Enable) {
			ctx.beginPath();
			ctx.setLineDash([4, 4]);
			ctx.fillStyle = "green";
			ctx.strokeStyle  = "green";
			ctx.font = "15px Arial";
			y_pos = canvas.height / 2 - canvas.height * g_init_cfg_json.Ch1Gnd  / g_init_cfg_json.Ch1Div / g_init_cfg_json.TimeDivNum;
			ctx.moveTo(0, parseInt(y_pos));
			ctx.lineTo(parseInt(canvas.width), parseInt(y_pos));
			ctx.fillText("Ch1Gnd", 0, y_pos);
			ctx.stroke();
		}
	}

	function UpdateWaveFps() {
		var canvas = document.getElementById("canvasWave");
		var ctx = canvas.getContext('2d');

		var current_time = Date.now();
		g_frame_cnt = g_frame_cnt + 1;
		if (current_time - g_last_update_time > 1000) {
			g_frame_fps = parseInt(g_frame_cnt * 1000 / (current_time - g_last_update_time) * 10) / 10;
			g_frame_cnt = 0;
			g_last_update_time = current_time;
			//console.log("FPS:" + g_frame_fps);
		}

		ctx.beginPath();
		ctx.fillStyle = "black";
		ctx.strokeStyle  = "black";
		ctx.font = "15px Arial";
		ctx.fillText("FPS:" + g_frame_fps, 0, canvas.height);
		ctx.stroke();
	}

	function UpdateWaveTimeDiv() {
		var canvas = document.getElementById("canvasWave");
		var ctx = canvas.getContext('2d');

		ctx.beginPath();
		ctx.fillStyle = "black";
		ctx.strokeStyle  = "black";
		ctx.font = "15px Arial";
		ctx.fillText("时间分度:" + g_init_cfg_json.TimeDivLable, canvas.width / 5, canvas.height);
		ctx.stroke();
	}

	function UpdateWaveData() {
		if (g_init_cfg_json.Ch0Enable) {
			UpdateWaveDataCh(0);
		}
		if (g_init_cfg_json.Ch1Enable) {
			UpdateWaveDataCh(1);
		}
	}

	function UpdateWaveMeasue() {
		if (g_init_cfg_json.Ch0Enable) {
			UpdateWaveMeasueCh(0);
		}
		if (g_init_cfg_json.Ch1Enable) {
			UpdateWaveMeasueCh(1);
		}
	}

	function UpdateWaveTime() {
		var canvas = document.getElementById("canvasWave");
		var ctx = canvas.getContext('2d');

		ctx.beginPath();
		ctx.fillStyle = "black";
		ctx.strokeStyle  = "black";
		ctx.font = "15px Arial";			
		ctx.fillText("计数(S):" + Math.floor(new Date().getTime() / 1000) % 10, canvas.width * 9 / 10, canvas.height);
		ctx.stroke();
	}

	function UpdateWaveClear() {
		var canvas = document.getElementById("canvasWave");
		var ctx = canvas.getContext("2d");

		ctx.clearRect(0, 0, canvas.width, canvas.height);
	}

	function UpdateWaveUi(responseText) {
		g_rt_data_json = JSON.parse(responseText);
		if (g_init_cfg_json == null) {
			return;
		}
		UpdateWaveStatus();
		UpdateWaveClear();
		UpdateWaveUiBackGrid();
		if (g_rt_data_json.Points.length != 0) {
			UpdateWaveData();
			UpdateWaveMeasue();
		}
		UpdateWaveGnd();
		UpdateWaveTimeDiv();
		UpdateWaveFps();
		UpdateWaveTime();
	}

	function SendVersionCb(responseText) {
		console.log("version: " + responseText);
		document.getElementById("Version").innerText = "版本: " + responseText;
	}

	function Ch0EnableChange(checkbox) {
		if (checkbox.checked) {			
			document.getElementById("Ch0Range").disabled = "";
			document.getElementById("Ch0Coupling").disabled = "";
			SendWriteSettingRequeset("Ch0Enable=1");
		} else {
			document.getElementById("Ch0Range").disabled = "disabled";
			document.getElementById("Ch0Coupling").disabled = "disabled";
			SendWriteSettingRequeset("Ch0Enable=0");
		}
	}

	function Ch1EnableChange(checkbox) {
		if (checkbox.checked) {			
			document.getElementById("Ch1Range").disabled = "";
			document.getElementById("Ch1Coupling").disabled = "";
			SendWriteSettingRequeset("Ch1Enable=1");
		} else {
			document.getElementById("Ch1Range").disabled = "disabled";
			document.getElementById("Ch1Coupling").disabled = "disabled";
			SendWriteSettingRequeset("Ch1Enable=0");
		}
	}
	function Ch0DivAdd() {
		SendWriteSettingRequeset("Ch0DivAdd=1");
	}
	function Ch0DivDec() {
		SendWriteSettingRequeset("Ch0DivDec=1");
	}
	function Ch1DivAdd() {
		SendWriteSettingRequeset("Ch1DivAdd=1");
	}
	function Ch1DivDec() {
		SendWriteSettingRequeset("Ch1DivDec=1");
	}
	function Ch0CouplingChange(checkbox) {
		SendWriteSettingRequeset("Ch0Coupling=" + checkbox.value);
	}
	function Ch1CouplingChange(checkbox) {
		SendWriteSettingRequeset("Ch1Coupling=" + checkbox.value);
	}
	function TriggerChnlChange(checkbox) {
		SendWriteSettingRequeset("TriggerChnl=" + checkbox.value);
	}
	function TriggerEdgeChange(checkbox) {
		SendWriteSettingRequeset("TriggerEdge=" + checkbox.value);
	}
	function MeasueFlagChange(checkbox, chnl, index) {
		if (checkbox.checked) { 
			SendWriteSettingRequeset("MeasureFlagSet=" + (1 << (index + chnl * 16)));
		} else { 
			SendWriteSettingRequeset("MeasureFlagClear=" + (1 << (index + chnl * 16)));
		}
	}
	function TriggerModeChange(checkbox) {
		SendWriteSettingRequeset("TriggerMode=" + checkbox.value);
	}
	function SendWriteRunSetting() {
		if (g_rt_data_json.Status == "Running") {
			SendWriteSettingRequeset("Running=0");
		} else {
			SendWriteSettingRequeset("Running=1");
		}
	}

	function CanvasCheckPos(mouseEvent, y_pos) {
		var canvas = document.getElementById("canvasWave");
		var ctx = canvas.getContext('2d');
		var rect = canvas.getBoundingClientRect();
		var word_width = rect.width / 20;
		var word_height = rect.height / 60;

		ctx.font = "15px Arial";
		if (mouseEvent.clientX > rect.left && mouseEvent.clientX < rect.left + word_width &&
			mouseEvent.clientY <= rect.top + y_pos + word_height && mouseEvent.clientY > rect.top + y_pos - word_height) {
			return true;
		}
		return false;
	}

	function CanvasInTriggerPos(mouseEvent) {
		var y_pos = 0;
		var canvas = document.getElementById("canvasWave");

		if (g_init_cfg_json.TriggerCh == 0) {
			y_pos = canvas.height / 2 - canvas.height * (g_init_cfg_json.TriggerLevel + g_init_cfg_json.Ch0Gnd) / g_init_cfg_json.Ch0Div / g_init_cfg_json.TimeDivNum;
		} else {
			y_pos = canvas.height / 2 - canvas.height * (g_init_cfg_json.TriggerLevel + g_init_cfg_json.Ch1Gnd) / g_init_cfg_json.Ch1Div / g_init_cfg_json.TimeDivNum;
		}		
		return CanvasCheckPos(mouseEvent, y_pos);
	}

	function CanvasInCh0GndPos(mouseEvent) {
		var canvas = document.getElementById("canvasWave");
		return CanvasCheckPos(mouseEvent, canvas.height / 2 - canvas.height * g_init_cfg_json.Ch0Gnd  / g_init_cfg_json.Ch0Div / g_init_cfg_json.TimeDivNum);
	}

	function CanvasInCh1GndPos(mouseEvent) {	
		var canvas = document.getElementById("canvasWave");
		return CanvasCheckPos(mouseEvent, canvas.height / 2 - canvas.height * g_init_cfg_json.Ch1Gnd  / g_init_cfg_json.Ch1Div / g_init_cfg_json.TimeDivNum);
	}

	function scaleCanvas(mouseEvent){
		var canvas = document.getElementById("canvasWave");
		var rect = canvas.getBoundingClientRect();
		var event = window.event || mouseEvent; 
		var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));
		var value = parseInt(event.clientX - rect.left) | ((parseInt(delta) & 0xFFFF) << 16);

		console.log(event);
		console.log("SnapScale=" + value);
		SendWriteSettingRequeset("SnapScale=" + value);

		if(event.preventDefault) {
			event.preventDefault();
		}
	}

	function CanvasInit() {
		var canvas = document.getElementById('canvasWave');
		var ctx = canvas.getContext('2d');
		var dragging_trigger = false;
		var dragging_ch0 = false;
		var dragging_ch1 = false;
		var dragging_move = false;
		var dragging_move_offset = 0;

		canvas.addEventListener("mousewheel", scaleCanvas, false);
		// Firefox
		canvas.addEventListener("DOMMouseScroll", scaleCanvas, false);

		canvas.addEventListener('mousedown', function(e) {
				if (CanvasInTriggerPos(e)) {
					dragging_trigger = true;
					return;
				}
				if (g_init_cfg_json.Ch0Enable && CanvasInCh0GndPos(e)) {
					dragging_ch0 = true;
					return;
				}
				if (g_init_cfg_json.Ch1Enable && CanvasInCh1GndPos(e)) {
					dragging_ch1 = true;
					return;
				}
				dragging_move = true;
				dragging_move_offset = e.clientX;
			}
		);

		canvas.addEventListener('mousemove', function(e) {
				var y_pos = canvas.height / 2 - (e.clientY - canvas.offsetTop);
				if (dragging_trigger) {
					if (g_init_cfg_json.TriggerCh == 0) {
						var value = parseInt(y_pos * g_init_cfg_json.Ch0Div * g_init_cfg_json.TimeDivNum / canvas.height);
						g_init_cfg_json.TriggerLevel = value - g_init_cfg_json.Ch0Gnd;
					} else {
						var value = parseInt(y_pos * g_init_cfg_json.Ch1Div * g_init_cfg_json.TimeDivNum / canvas.height);
						g_init_cfg_json.TriggerLevel = value - g_init_cfg_json.Ch1Gnd;
					}		
					UpdateWaveUiBackGrid();
				}
				if (dragging_ch0) {
					g_init_cfg_json.Ch0Gnd = parseInt(y_pos * g_init_cfg_json.Ch0Div * g_init_cfg_json.TimeDivNum / canvas.height);
					SendWriteSettingRequeset("Ch0Gnd=" + g_init_cfg_json.Ch0Gnd);
					UpdateWaveUiBackGrid();
				}
				if (dragging_ch1) {
					g_init_cfg_json.Ch1Gnd = parseInt(y_pos * g_init_cfg_json.Ch1Div * g_init_cfg_json.TimeDivNum / canvas.height);
					SendWriteSettingRequeset("Ch1Gnd=" + g_init_cfg_json.Ch1Gnd);
					UpdateWaveUiBackGrid();
				}
				if (dragging_move) {
					var offset = dragging_move_offset - e.clientX;
					dragging_move_offset = e.clientX;
					SendWriteSettingRequeset("SnapMove=" + offset);
				}
			}
		);

		canvas.addEventListener('mouseup', function() {
				if (dragging_trigger) {
					dragging_trigger = false;
					SendWriteSettingRequeset("TriggerLevel=" + g_init_cfg_json.TriggerLevel);
				}
				dragging_ch0 = false;
				dragging_ch1 = false;
				dragging_move = false;
			}
		);

		canvas.addEventListener('mouseout', function() {
				if (dragging_trigger) {
					dragging_trigger = false;
					SendWriteSettingRequeset("TriggerLevel=" + g_init_cfg_json.TriggerLevel);
				}
				dragging_ch0 = false;
				dragging_ch1 = false;
				dragging_move = false
			}
		);
	}

    window.onload = function() {
		CanvasInit();
		UpdateWaveUiBackGrid();
		SendReadSettingRequeset();
		SendHttpRequest("/version.txt", SendVersionCb);
    }
</script>
</body>
</html>
